package lumis.service.locale;

import lumis.doui.processaction.ProcessActionHandler;
import lumis.doui.source.Source;
import lumis.portal.PortalException;
import lumis.portal.PortalObjectNotFoundException;
import lumis.portal.UnexpectedException;
import lumis.portal.localization.CustomStringConfig;
import lumis.portal.localization.LocaleConfig;
import lumis.portal.manager.ManagerFactory;
import lumis.portal.manager.ManagerFactoryInternal;
import lumis.portal.url.WebResource;
import lumis.portal.url.IURLManager.CreateStrategy;
import lumis.util.CookieUtil;
import lumis.util.LocaleUtil;
import lumis.util.XmlUtil;

import java.io.IOException;
import java.util.Collection;
import java.util.Locale;

import javax.persistence.NoResultException;

/**
 * Sets the current user's locale to the locale specified in the
 * <code>locale</code> request parameter.
 * @version $Revision: 13092 $ $Date: 2011-05-28 18:19:06 -0300 (Sat, 28 May 2011) $
 * @since 4.0.10
 */
@SuppressWarnings("unchecked")
public class LocaleProcessActionHandler extends ProcessActionHandler<Source<?>>
{
	public static final String SET_LOCALE = "setLocale";
	public static final String CLEAR_CACHE = "clearCache";
	public static final String ADD_OR_UPDATE_CUSTOM_STRING = "addOrUpdateCustomString";
	public static final String DELETE_CUSTOM_STRING = "deleteCustomString";
	public static final String DELETE_LOCALE = "deleteLocale";
	
	public void processAction() throws PortalException 
	{
		String actionType = XmlUtil.readAttributeString("actionType", processActionNode);

		if (actionType.equals(LocaleProcessActionHandler.SET_LOCALE))
			setLocale();
		else if (actionType.equals(LocaleProcessActionHandler.CLEAR_CACHE))
			clearCache();
		else if (actionType.equals(LocaleProcessActionHandler.ADD_OR_UPDATE_CUSTOM_STRING))
			addOrUpdateCustomString();
		else if (actionType.equals(LocaleProcessActionHandler.DELETE_CUSTOM_STRING))
			deleteCustomString();
		else if (actionType.equals(DELETE_LOCALE))
			deleteLocale();
	}

	/**
	 * Method called when locales are been deleted from administration
	 * interface.
	 * 
	 * @since 6.0.0
	 */
	private void deleteLocale() throws PortalException
	{
		String[] localeIds = getParameter("localeId", String[].class);
		if (localeIds == null || localeIds.length == 0)
			return;

		for (String localeId : localeIds)
		{
			try
			{
				ManagerFactory.getEntityManager().createNativeQuery(
								"select wr.id from lum_WebResource wr inner join lum_Locale l on wr.locale = l.locale where l.localeId = :localeId")
						.setMaxResults(1).setParameter("localeId", localeId).getSingleResult();
			}
			catch (NoResultException e)
			{
				// no WR with the given locale was found. continue.
				continue;
			}
			// a WR with the given locale has been found. terminate operation.
			throw new PortalException(localize("STR_LOCALE_TO_BE_DELETED_IS_BEEN_USED"));
		}
	}

	public void setLocale() throws PortalException 
	{
		String localeId = douiContext.getRequest().getParameter("locale");
		Locale locale;
		if (localeId != null)
		{
			locale = LocaleUtil.FromString(localeId);
			douiContext.getRequest().getSessionConfig().setLocale(locale);
			CookieUtil.addLumisUserCookies(douiContext.getRequest(), douiContext.getResponse());
		}
		else
			return;
		
		String currentUrl = douiContext.getRequest().getParameter("currentUrl");
		if(currentUrl != null)
		{
			String redirectPath;
			
			int curIndex = 0;
			for(int i=0; i<3; i++)
			{
				curIndex = currentUrl.indexOf('/', curIndex+1);
				if(curIndex == -1)
					break;
			}
			
			if(curIndex == -1)
			{
				redirectPath = "/";
			}
			else
			{
				String contextUrl = lumis.util.PortalUtil.getWebsiteUri(((javax.servlet.http.HttpServletRequest)douiContext.getRequest()));
				currentUrl = currentUrl.substring(curIndex);
				
				if(currentUrl.startsWith(contextUrl))
				{
					currentUrl = currentUrl.substring(contextUrl.length());
				}
				else
				{
					addDefaultResponse();
					return;
				}
				
				boolean isDynamicUrl = false;
				if(currentUrl.startsWith("/main.jsp"))
					isDynamicUrl = true;
				
				if(!isDynamicUrl)
				{
					String html = "href=\""+currentUrl.substring(1)+"\"";
					html = ManagerFactoryInternal.getURLManager().convertHTMLPathsToDynamicPaths(html);
					html = html.substring(6);
					currentUrl = "/"+html.substring(0, html.length()-1);
				}
				
				// make sure a valid web resource already exists for the given
				// url
				WebResource webResource;
				try
				{
					// verify if web resource for the given url exists in chosen
					// locale
					webResource = ManagerFactoryInternal.getURLManager()
							.getWebResourceByDynamicPath(currentUrl, CreateStrategy.NEVER, locale);
				}
				catch (PortalObjectNotFoundException e)
				{
					// if web resource for the given url doesn't exists in
					// chosen locale, verify if same dynamic path exists for other locale
					boolean foundValidWebResource = false;
					Collection<LocaleConfig> locales = ManagerFactory.getLocalizationManager().getLocales(transaction);
					for (LocaleConfig localeConfig : locales)
					{
						if (localeConfig.getLocale().equals(locale.toString()))
							continue;
						try
						{
							ManagerFactoryInternal.getURLManager().getWebResourceByDynamicPath(currentUrl,
									CreateStrategy.NEVER, LocaleUtil.FromString(localeConfig.getLocale()));
						}
						catch (PortalObjectNotFoundException e1)
						{
							continue;
						}
						foundValidWebResource = true;
						break;
					}
					
					if (!foundValidWebResource)
						throw new UnexpectedException(new IllegalArgumentException(
								"No valid web resource for given URL was found."));
					
					// since another equivalent web resource exists in another
					// locale, allow the creation of the web resource for the
					// requested locale
					webResource = ManagerFactoryInternal.getURLManager().getWebResourceByDynamicPath(currentUrl,
								CreateStrategy.AUTO, locale);
				}

				redirectPath = webResource.getPath();
			}
			
			try
			{
				douiContext.getActionResponse().sendRedirect(douiContext.getActionRequest().getContextPath() + redirectPath);
			}
			catch(IOException e)
			{
				throw new UnexpectedException(e);
			}
		}
		else
		{
			addDefaultResponse();
		}
	}
	
	public void clearCache() throws PortalException 
	{
		
		ManagerFactory.getLocalizationManager().clearCache();
		
		addDefaultResponse();
	}
	
	public void addOrUpdateCustomString() throws PortalException
	{	
		String customStringId = (String)getParameter("customStringId");
		String stringId = (String)getParameter("stringId");
		String string = (String)getParameter("string");
		String resourcePath = (String)getParameter("resourcePath");
		String localeCode = (String)getParameter("localeCode");
		Number status = (Number)getParameter("status");
		
		CustomStringConfig customStringConfig = new CustomStringConfig();

		customStringConfig.setCustomStringId(customStringId);
		customStringConfig.setStringId(stringId);
		customStringConfig.setString(string);
		customStringConfig.setResourcePath(resourcePath);
		customStringConfig.setLocaleCode(localeCode);
		customStringConfig.setStatus(status.intValue());
		
		if (customStringId == null)
			ManagerFactory.getLocalizationManager().addCustomString(sessionConfig, customStringConfig, transaction);
		else
			ManagerFactory.getLocalizationManager().updateCustomString(sessionConfig, customStringConfig, transaction);
		
		addDefaultResponse();
	}
	
	public void deleteCustomString() throws PortalException
	{
		String[] customStringIds = (String[]) getParameter("customStringId");
		for (String customStringId : customStringIds)
		{
			ManagerFactory.getLocalizationManager().deleteCustomString(sessionConfig, customStringId, transaction);
		}
		
		addDefaultResponse();
	}
}
